﻿using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WinAction.Action
{
	public static class MouseAction
	{
		/// <summary>
		/// 鼠标事件枚举
		/// </summary>
		[Flags]
		public enum MouseEventFlag : int
		{
			Move = 0x001,
			LeftDown = 0x002,
			LeftUp = 0x004,
			RightDown = 0x008,
			RightUp = 0x0010,
			MiddleDown = 0x0020,
			MiddleUp = 0x0040,
			Absolute = 0x8000,
			Wheel = 0x0800
		}


		// 模拟鼠标事件
		[DllImport("user32")]
		private static extern int mouse_event(MouseEventFlag dwFlags, int dx, int dy, int dwData, int dwExtraInfo);

		/// <summary>
		/// 将指定的x,y转化为屏幕对应的坐标
		/// </summary>
		/// <param name="x">x坐标</param>
		/// <param name="y">y坐标</param>
		/// <returns>屏幕对应的坐标</returns>
		private static Point TransferPosToScreen(int x, int y)
		{
			int width = Screen.PrimaryScreen.Bounds.Width;
			int height = Screen.PrimaryScreen.Bounds.Height;
			x = (int)((double)x / width * 0xffff);
			y = (int)((double)y / height * 0xffff);
			return new Point(x, y);
		}

		/// <summary>
		/// 移动鼠标到指定位置
		/// </summary>
		/// <param name="x">x坐标</param>
		/// <param name="y">y坐标</param>'
		/// <returns>转换后对应屏幕位置的坐标点</returns>
		public static Point MouseMove(int x, int y)
		{
			Point point = TransferPosToScreen(x, y);
			mouse_event(MouseEventFlag.Absolute | MouseEventFlag.Move, point.X, point.Y, 0, 0);
			return point;
		}

		/// <summary>
		/// 点击指定位置
		/// </summary>
		/// <param name="x">x坐标</param>
		/// <param name="y">y坐标</param>
		public static void MouseClick(int x, int y)
		{
			Point point = MouseMove(x, y);
			mouse_event(MouseEventFlag.LeftDown | MouseEventFlag.Absolute | MouseEventFlag.LeftUp, point.X, point.Y, 0, 0);
		}

		/// <summary>
		/// 双击指定位置
		/// </summary>
		/// <param name="x">x坐标</param>
		/// <param name="y">y坐标</param>
		public static async void MouseDbClick(int x, int y)
		{
			MouseClick(x, y);
			await Task.Delay(200);
			MouseClick(x, y);
		}

		/// <summary>
		/// 鼠标长按
		/// </summary>
		/// <param name="x">x坐标</param>
		/// <param name="y">y坐标</param>
		/// <param name="time">按下时间(默认3秒)</param>
		public static async void MouseLongClick(int x, int y, int time = 3000)
		{
			Point point = MouseMove(x, y);
			mouse_event(MouseEventFlag.LeftDown | MouseEventFlag.Absolute, point.X, point.Y, 0, 0);
			await Task.Delay(time);
			mouse_event(MouseEventFlag.LeftUp | MouseEventFlag.Absolute, point.X, point.Y, 0, 0);
		}

		/// <summary>
		/// 鼠标按下
		/// </summary>
		/// <param name="x">x坐标</param>
		/// <param name="y">y坐标</param>
		public static void MouseDown(int x, int y)
		{
			Point point = MouseMove(x, y);
			mouse_event(MouseEventFlag.LeftDown | MouseEventFlag.Absolute, point.X, point.Y, 0, 0);
		}

		/// <summary>
		/// 鼠标抬起
		/// </summary>
		/// <param name="x">x坐标</param>
		/// <param name="y">y坐标</param>
		public static void MouseUp(int x, int y)
		{
			Point point = MouseMove(x, y);
			mouse_event(MouseEventFlag.LeftUp | MouseEventFlag.Absolute, point.X, point.Y, 0, 0);
		}

		/// <summary>
		/// 鼠标拖拽
		/// </summary>
		/// <param name="x1">第一个点的x坐标</param>
		/// <param name="y1">第一个点的y坐标</param>
		/// <param name="x2">第二个点的x坐标</param>
		/// <param name="y2">第二个点的y坐标</param>
		public static void MouseDrag(int x1, int y1, int x2, int y2)
		{
			Point point1 = MouseMove(x1, y1);
			mouse_event(MouseEventFlag.LeftDown | MouseEventFlag.Absolute, point1.X, point1.Y, 0, 0);
			Point point2 = MouseMove(x2, y2);
			mouse_event(MouseEventFlag.LeftUp | MouseEventFlag.Absolute, point2.X, point2.Y, 0, 0);
		}

		/// <summary>
		/// 移动鼠标滚轮至指定距离
		/// </summary>
		/// <param name="distance">距离</param>
		public static void MouseScroll(int distance)
		{
			mouse_event(MouseEventFlag.Wheel, 0, 0, distance, 0);
		}

		/// <summary>
		/// 点击右键
		/// </summary>
		/// <param name="x">x坐标</param>
		/// <param name="y">y坐标</param>
		public static void RightClick(int x, int y)
		{
			var point = MouseMove(x, y);
			mouse_event(MouseEventFlag.Absolute | MouseEventFlag.RightDown | MouseEventFlag.RightUp, point.X, point.Y, 0, 0);
		}

		/// <summary>
		/// 点击中键
		/// </summary>
		/// <param name="x">x坐标</param>
		/// <param name="y">y坐标</param>
		public static void MiddleClick(int x, int y)
		{
			var point = MouseMove(x, y);
			mouse_event(MouseEventFlag.Absolute | MouseEventFlag.MiddleDown | MouseEventFlag.MiddleUp, point.X, point.Y, 0, 0);
		}
	}
}
